

import React from 'react'

// 1、Typescript原始数据类型：

// string
// number
// boolean
// null
// undefined
// enum
// symbol

// 空值一般采用void表示，void可以表示变量，也可以表示函数返回值。

// 任意值（any）用来表示允许赋值为任意类型。 
// 变量如果在申明的时候如果未指定其类型，那么它会被识别为任意值类型。 
const Demo = () => {
    let a; // a是任意类型  
    let b = 1; // b是number类型   Typescript会依照类型推论的规则推断出一个类型。 

    const c: string | number = 1; // 联合类型表示取值可以为多种类型中的一种。 

    const flag:boolean = true;
    const toggle:boolean  = !!0;
    const d:number = 111;
    const e:string = '1222'

    // Typescript中对象类型-接口：   interface  
    // 可描述类的一部分抽象行为，也可描述对象的结构形状。 接口一般首字母大些 

    interface Istate1 {
        name: string;
        age: number;
    }
    const obj:Istate1 = {
        name:'Tom',
        age:20 
    }

    // 可选属性
    interface Istate2 {
        name: string;
        age?: number;   // 字段可写可不写
    }

    const obj2: Istate2 = {
        name: "张三",
        age: 18
    }

    // 属性个数不确定的时候， any必须是任意类型
    interface Istate3 {
        name: string|number;
        age?: number;
        [propName: string]: any;
    }

    const obj33: Istate3 = {
        name: 'Jay',
        age: 20,
        sex: "men",
        isMary: false,
        birth:"06-15"
    }

    // 只读属性
    interface Istate4{
        name: string;
        readonly age: number;
    }

    const obj4: Istate4 = {
        name: "Jack",
        age: 55
    }
    // obj4.age = 18;  不可改 

    // 6、Typescript数组类型：
    // 1) 可采用"类型[]"法表示；
    const arr:number[] = [1,2,3,4]
    const arr2:string[] = ['vue','react']
    const arr3:Istate4[] = [{
        name: "Jack",
        age: 55
    }]
    // 2) 可采用数组泛型“Array<类型>”表示法；

    const arr4:Array<string> = ["2","3","4"]
    const arr5:Array<number> = [10,200,300]

    // 3) 可采用接口表示法。

    const arr6:Array<Istate1> = [
        {
            age:1,
            name:'123123'
        }
    ] 

    // 4）class 类型  Array<Comment>
    const arr7: Comment[] = [
        new Comment(1,'happy','Who Happy','ZKl'),
        new Comment(1,'happy','Who Happy','ZKl'),
        new Comment(1,'happy','Who Happy','ZKl'),
        new Comment(1,'happy','Who Happy','ZKl'),
    ]

    // 7、Typescript函数类型：
    // 函数约束：有函数本身的参数约束，返回值约束；
    // 还有函数本身赋值的变量的约束；
    // void 空 没有返回 

    // 申明式类型的函数
    function funType0(name: string, age: number):void  {
        
    }

    function funType(name: string, age: number):string  {
        return name;
    }

    const uesrName: string = funType("Tom", 18);

    // 函数参数不确定
    function funType2(name: string, age: number, sex?: string): number{
        return age;
    }

    const age2Number = funType2("Tom", 18, "男");

    // 函数参数的默认值 直接定义类型 
    function funType3(name="Tom", age=18): number{
        return age;
    }

    const age3Number = funType3();


    // 表达式类型的函数
    const funType4 = function(name: string, age: number): number{
        return age;
    }

    // 函数类型 
    const funType5: (name: string, age: number) => number  = function(name: string, age: number): number{
        return age;
    }

    interface IfunType6{
        (name: string, age: number): number;
    }
    
    const funType6: IfunType6 = function(name: string, age: number): number{
        return age;
    }

    const funType7 = function(name:string,age:number){
        return age;
    }

    // 8、Typescript类型断言：
    // 类型断言可以用来手动指定一个值的类型。
    // 语法：<类型>值或者值 as 类型。
    // res as any ;
    // 类型断言 只能断言联合类型中存在的类型
    // 
    // const age  = 1000 as any;
    function getAssert(name: string|number){
        //return (<string>name).length;
        return (name as string).length;
    }

    // 9、Typescript类型别名：
    // type 
    // 类型别名可以用来给一个类型起一个新名字。
    type strType = string | number | boolean;
    let str: strType = "1"

    type allTypes = string | number | boolean | undefined | null | symbol 
    
    type someIstate = Istate3 | Istate4 | Istate2 ; 

    // 限制字符串的选择
    type sex = "男" | "女";

    type loginType = 'mobile' | 'account'

    // 10、Typescript枚举： 
    // 枚举（enum）类型用于取值被限定在一定范围内的场景。 
    // 采用关键字enum定义，比如：enum days{Sun， Mon, Tue, Wed, Thu, Fri, Sat}。
    // 使用枚举可以定义一些有名字的数字常量
    enum Days{
        Sun,
        Mon,
        Tue,
        Wed, 
        Thu, 
        Fri, 
        Sat
    }
    console.log(Days.Sun); // 0
    console.log(Days.Sat); // 6
    console.log(Days); // {0: "Sun", 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat", Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, …}
    console.log(Days[0] === "Sun"); // True

    enum Sexs{
        Female,
        Male
    }

  
    console.log(Sexs.Female) 
    console.log(Sexs.Male) 

    enum Types{
        '已发货',
        noSend,
        noPay,
        hasPay,
    }
    console.log(Types[0])
    console.log(Types['已发货'])


    // 11、Typescript类的装饰符：
    // public、private和protected。

    // 12、Typescript泛型： T
    // 泛型是指在定义函数、接口或类的时候，不预先指定具体类型，而是在使用的时候再指定类型的一种特性。

    // 函数中使用泛型
    function createArr<T>(length: number, value: T): Array<T>{
        const arr = [];
        for(let i = 0; i<length; i++){
            arr[i] = value;
        }

        return arr;
    }
    const strArr: string[] = createArr(8,"a");
    const strArr2: boolean[] = createArr(4,true);
    const strArr3: number[] = createArr(4,1);
    
    // 接口当中使用泛型
    interface Icreate{
        <T>(name: string, value: T): Array<T>;
    }

    const func: Icreate = function<T>(name: string, value: T): Array<T>{
        var arr : Array<T> = []
        for(var i = 0;i<10;i++){
            arr.push(value) 
        }
        return arr;
    }

    const strArr6: number[] = func("Jack", 3);
    const strArr7: boolean[] = func("Jack", !!1);

    // 实战 使用 TS 


    return (
        <div>
            <h2> Demo - Demo - Demo </h2>
            <h1>简单学习 typescript </h1>
        </div>
    )
}
// public 公有变量
// private 私有变量
// protected 被保护的变量


class Comment{
    constructor(
       public id:number,
       public title:string,
       public content:string, 
       public author:string
    ){

    }
}

export default Demo